package com.hera.base.util;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.BeanUtilsBean2;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;

import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.server.Sizeable;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.PopupDateField;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;


public class TableCustom extends VerticalLayout implements Serializable {

	private static final long serialVersionUID = 1L;
	private List<PropiedadTableCustom> lstPropiedades;
	private List lstData;
	private Table table = null;
	HorizontalLayout lytFiltro = null;
	VerticalLayout lytTitulo = null;
	AbstractField[] txtFiltro = null;
	private String titulo;
	String height="-1px";
	
	int NRO_PIXELES=13;
	private List<String> lstAlias;
	
	public TableCustom(String titulo) {
		lstPropiedades = new ArrayList<PropiedadTableCustom>();
		lstAlias=new ArrayList<String>();
		this.setTitulo(titulo);
		BeanUtilsBean.setInstance(new BeanUtilsBean2());
        DateConverter converter = new DateConverter();
        converter.setPattern("dd/MM/yyyy");
        ConvertUtils.register(converter, Timestamp.class);
		    
        DateConverter converter2 = new DateConverter();
        converter2.setPattern("dd/MM/yyyy");
        ConvertUtils.register(converter2, Date.class);

	}
	public TableCustom() {
		this("");
	}

	public void addColumn(String columna, String etiqueta, Integer tamanio, boolean visible, Class<?> tipo) {
		PropiedadTableCustom propiedad = new PropiedadTableCustom();
		propiedad.setOrden(lstPropiedades.size() + 1);
		propiedad.setColumna(columna);
		propiedad.setEtiqueta(etiqueta);
		propiedad.setTipo(tipo);
		propiedad.setTamanio(tamanio);
		propiedad.setVisible(visible);
		lstPropiedades.add(propiedad);
	}

	public Object[] getVisibleColumns() {
		List<String> lstNombre = new ArrayList<String>();
		for (PropiedadTableCustom propiedad : lstPropiedades) {
			if (propiedad.getVisible()) {
				lstNombre.add(propiedad.getColumna());
			}
		}
		return lstNombre.toArray();
	}

	public Object obtenerValor(Field[] fields, String campo, Object obj) throws Exception {
		for (int i = 0; i < fields.length; i++) {
			if (fields[i].getName().equals(campo)) {
				return fields[i].get(obj);
			}

		}
		throw new RuntimeException("Nombre de campo no encontrado");
	}

	public void construir() {
		setImmediate(false);
		setMargin(false);
		construirTabla();
		height=((int)getHeight())+"";
		setHeight("-1px");
		setWidth("-1px");
		construirFiltro();
		addComponent(lytTitulo);
		addComponent(getTable());
	}

	private void construirTabla() {

		setTable(new Table());
		table.setId(getId()+"__");
		getTable().setSelectable(true);
		getTable().setImmediate(true);
		getTable().setNullSelectionAllowed(true);
		getTable().setNullSelectionItemId(null);
		getTable().setWidth(getTamanio()+"px");
		

		

	}

	private void construirFiltro() {
		lytTitulo=new VerticalLayout();
		lytTitulo.setSpacing(true);
		Label lblTitulo=new Label();
		lblTitulo.setValue(getTitulo());
		lblTitulo.setStyleName("titulo");
		lytTitulo.addComponent(lblTitulo);
		lytFiltro = new HorizontalLayout(); 	
		lytFiltro.setImmediate(false);
		lytFiltro.setWidth("-1px");
		lytFiltro.setHeight("-1px");
		lytFiltro.setMargin(false);
		txtFiltro = new AbstractField[lstPropiedades.size()];
		int index = 0;
		
		for (PropiedadTableCustom propiedad : lstPropiedades) {
			if(propiedad.getTipo()==Date.class){
				PopupDateField filtrocampoFecha=new PopupDateField();
				filtrocampoFecha.setDateFormat("dd/MM/yyyy");
//				filtrocampoFecha.setTextFieldEnabled(false);
				filtrocampoFecha.setId("txtd" +table.getId()+ propiedad.getColumna());
				filtrocampoFecha.setWidth(propiedad.getTamanio() + NRO_PIXELES, Sizeable.Unit.PIXELS);
				filtrocampoFecha.setImmediate(true);
				filtrocampoFecha.setHeight("-1px");
				filtrocampoFecha.setInputPrompt(propiedad.getEtiqueta());
				txtFiltro[index++] = filtrocampoFecha;
				lytFiltro.addComponent(filtrocampoFecha);
			}else{
				TextField filtroColumna = new TextField();
				filtroColumna.setId("txtf" +table.getId()+ propiedad.getColumna());
				filtroColumna.setWidth(propiedad.getTamanio() + NRO_PIXELES, Sizeable.Unit.PIXELS);
				filtroColumna.setImmediate(true);
				filtroColumna.setHeight("-1px");
				filtroColumna.setInputPrompt(propiedad.getEtiqueta());
				txtFiltro[index++] = filtroColumna;
				lytFiltro.addComponent(filtroColumna);
			}
		}
		lytTitulo.addComponent(lytFiltro);
	}
	
	private int getTamanio() {
		int width = 0;
		for (PropiedadTableCustom propiedad : lstPropiedades) {
			width += propiedad.getTamanio()+NRO_PIXELES;
		}
		return width+20;
	}

	public void addValueChangeListener(ValueChangeListener valueChangeListener) {
		if (valueChangeListener != null) {
			getTable().addListener((ValueChangeListener)valueChangeListener);
		}
	}

	public void addTextChangeListener(TextChangeListener textChangeListener) {
		for (AbstractField filtroColumna : txtFiltro) {
			if (textChangeListener != null) {
				if(filtroColumna instanceof TextField){
					((TextField)filtroColumna).addTextChangeListener(textChangeListener);
				}
				
			}
		}
	}

	public void addDateValueChangeListener(ValueChangeListener textChangeListener) {
		for (AbstractField filtroColumna : txtFiltro) {
			if (textChangeListener != null) {
				if(filtroColumna instanceof PopupDateField){
					((PopupDateField)filtroColumna).addValueChangeListener(textChangeListener);
				}
				
			}
		}
	}
	
	public List getLstData() {
		return lstData;
	}

	public Object getSelectedItem(ValueChangeEvent event) {
		Item item = table.getItem(table.getValue());
		if (item == null) {
			return null;
		}
		return item.getItemProperty("objectData").getValue();
		
	}

	public void limpiarFiltro(){
		for(AbstractField textField:txtFiltro){
			textField.setValue("");
		}
	}
	
	public void setLstData(List lstData) {
		this.lstData = lstData;
		
		IndexedContainer container = new IndexedContainer();
		for (PropiedadTableCustom propiedad : lstPropiedades) {
			if(propiedad.getTipo() ==Date.class){
				container.addContainerProperty(propiedad.getColumna(), String.class, null);
			}else{
				container.addContainerProperty(propiedad.getColumna(), propiedad.getTipo(), null);	
			}
			
		}
		container.addContainerProperty("objectData", Object.class, null);
		int con = 1;
		Class obj = null;
		for (Object row : lstData) {
			obj = row.getClass();
			Item item = container.addItem(con++);
			try {
				for (PropiedadTableCustom propiedad : lstPropiedades) {
					Object valor ="";
					try{
						valor = BeanUtils.getProperty(row, propiedad.getColumna());
					}catch (Exception e) {e.printStackTrace();}					
					if(propiedad.getTipo() ==Date.class){
						item.getItemProperty(propiedad.getColumna()).setValue(valor);
					}else{
						item.getItemProperty(propiedad.getColumna()).setValue(ConvertUtils.convert(valor, propiedad.getTipo()));	
					}
					
				}
				item.getItemProperty("objectData").setValue(row);
			} catch (RuntimeException e) {
				System.out.print("ERRORRR" + e.getMessage());
				e.printStackTrace();
			} catch (Exception e) {
				System.out.print("ERRORRR" + e.getMessage());
				e.printStackTrace();
			}
		}
		getTable().setContainerDataSource(container);
		getTable().setVisibleColumns(getVisibleColumns());
		
		for (PropiedadTableCustom propiedad : lstPropiedades) {
			getTable().setColumnWidth(propiedad.getColumna(), propiedad.getTamanio());
		}
		for (PropiedadTableCustom propiedad : lstPropiedades) {
			getTable().setColumnHeader(propiedad.getColumna(), propiedad.getEtiqueta());
		}
		getTable().setHeight(height+"px");
		getTable().setWidth(getTamanio()+"px");
	}
	
	public FiltroDTO getFiltroDTO(TextChangeEvent event){
		String[] alias=new String[lstAlias.size()];
		FiltroDTO filtroDTO=new FiltroDTO(lstAlias.toArray(alias));
		for(int i=0;i<getFiltros().length;i++){
			AbstractField aux=getFiltros()[i];
			if(aux instanceof TextField){
				TextField filtro=(TextField)aux;
				PropiedadTableCustom propiedad=getPropiedades().get(i);
				String valor=null;
				if(event!=null&&event.getSource().equals(filtro)){
					valor=event.getText().toUpperCase();
				}else{
					valor=filtro.getValue();	
				}
				if(propiedad.getTipo()==Long.class||propiedad.getTipo()==Integer.class
						||propiedad.getTipo()==Double.class||propiedad.getTipo()==Date.class){
					if(valor!=null&&!valor.equals("")){
						filtroDTO.addParametro(propiedad.getColumna(), ConvertUtils.convert(valor, propiedad.getTipo()));
					}	
				}else if(propiedad.getTipo()==String.class){
					filtroDTO.addParametroLike(propiedad.getColumna(), ConvertUtils.convert(valor, propiedad.getTipo()));
				}else{
					filtroDTO.addParametroLike(propiedad.getColumna(), ConvertUtils.convert(valor, propiedad.getTipo()));
				}
			}else if(aux instanceof PopupDateField){
				PopupDateField filtro=(PopupDateField)aux;
				PropiedadTableCustom propiedad=getPropiedades().get(i);
				Date valor=null;
				if(event!=null&&event.getSource().equals(filtro)){
//					valor=event.getText().toUpperCase();
				}else{
					valor=filtro.getValue();	
				}
				if(propiedad.getTipo()==Long.class||propiedad.getTipo()==Integer.class
						||propiedad.getTipo()==Double.class||propiedad.getTipo()==Date.class){
					if(valor!=null&&!valor.equals("")){
						filtroDTO.addParametro(propiedad.getColumna(), ConvertUtils.convert(valor, propiedad.getTipo()));
					}	
				}else if(propiedad.getTipo()==String.class){
					filtroDTO.addParametroLike(propiedad.getColumna(), ConvertUtils.convert(valor, propiedad.getTipo()));
				}else{
					filtroDTO.addParametroLike(propiedad.getColumna(), ConvertUtils.convert(valor, propiedad.getTipo()));
				}
			}
			
		}		
		return filtroDTO;
	}

	public AbstractField[] getFiltros() {
		return txtFiltro;
	}

	public Table getTable() {
		return table;
	}

	public void setTable(Table table) {
		this.table = table;
	}

	public List<PropiedadTableCustom> getPropiedades() {
		return lstPropiedades;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}
	public List<String> getLstAlias() {
		return lstAlias;
	}
	public void setLstAlias(List<String> lstAlias) {
		this.lstAlias = lstAlias;
	}
}